package main.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;
import java.util.List;
import javax.swing.JComponent;
import main.model.DataModel;
import main.model.Day;


/**
 * Canvas to visualize the data.
 *
 * @author Yaqi Zhang
 */

public class Canvas extends JComponent {

    /**
     *
     */
    private static final int INFO_BOX_SIZE = 200;
    private static final long serialVersionUID = 1L;
    private static final float RATIO_NUM = 9;
    private static final float RATIO_DEN = 10;
    private static final int INFO_BOX_START_LOC = (int)((RATIO_NUM / RATIO_DEN) * INFO_BOX_SIZE);
    private final int myWidth;
    private final int myHeight;
    private Graphics myPen;
    private Visualizer myVisual;
    private final Dimension mySize;
    private HashMap<Integer, List<Object>> myMap;
    private Day myDayToPrint;
    private Point myMouseLoc;

    /**
     * Constructor
     *
     * @param size Size of canvas
     */
    public Canvas (Dimension size) {
        mySize = size;
        myWidth = mySize.width;
        myHeight = mySize.height;
        setPreferredSize(size);
        setFocusable(true);
        requestFocus();
        myVisual = new Visualizer(null, mySize);
        this.addMouseMotionListener(makeMouseMotionListener());
    }

    private MouseMotionListener makeMouseMotionListener () {
        MouseMotionListener mmListener = new MouseAdapter() {
            @Override
            public void mouseMoved (MouseEvent e) {
                if (myMap != null) {
                    myMouseLoc = new Point(e.getX(), e.getY());
                    int mouseX = e.getX();
                    List<Object> dayInfo = myMap.get(mouseX);
                    if (dayInfo != null) {
                        if (isMouseOnBar(e, dayInfo)) {
                            Day d = (Day) dayInfo.get(2);
                            myDayToPrint = d;
                            repaint();
                        }
                    }
                }
            }

        };
        return mmListener;
    }

    private boolean isMouseOnBar (MouseEvent e, List<Object> dayInfo) {
        int highLoc = (Integer) dayInfo.get(0);
        int lowLoc = (Integer) dayInfo.get(1);
        int mouseY = e.getY();
        return (mouseY < lowLoc) && (mouseY > highLoc);
    }

    /**
     * Clears canvas
     *
     */
    public void clear () {
        myVisual = new Visualizer(null, mySize);
        repaint();
    }

    @Override
    protected void paintComponent (Graphics pen) {
        myPen = pen;
        myPen.setColor(Color.WHITE);
        myPen.fillRect(0, 0, myWidth, myHeight);
        myVisual.paint(pen);
        myMap = myVisual.getPointMap();
        paintDayInfo(pen);
    }

    private void paintDayInfo (Graphics pen) {
        if (myDayToPrint != null) {
            String date = myDayToPrint.getDate().toString();
            String high = Float.toString(myDayToPrint.getHigh());
            String low = Float.toString(myDayToPrint.getLow());
            String open = Float.toString(myDayToPrint.getOpen());
            String close = Float.toString(myDayToPrint.getClose());
            String volum = Float.toString(myDayToPrint.getVolume());
            pen.setColor(Color.WHITE);
            pen.fillRect(myMouseLoc.x - INFO_BOX_SIZE, myMouseLoc.y,
                    INFO_BOX_SIZE, INFO_BOX_SIZE);
            pen.setColor(Color.BLACK);
            pen.drawRect(myMouseLoc.x - INFO_BOX_SIZE, myMouseLoc.y,
                    INFO_BOX_SIZE, INFO_BOX_SIZE);
            int startX = myMouseLoc.x - INFO_BOX_START_LOC;
            final int Y_STEP = 20;
            int i = 0;
            pen.drawString(date, startX, myMouseLoc.y + (++i * Y_STEP));
            pen.drawString("High: " + high, startX, myMouseLoc.y + (++i * Y_STEP));
            pen.drawString("Low: " + low, startX, myMouseLoc.y + (++i * Y_STEP));
            pen.drawString("Open: " + open, startX, myMouseLoc.y + (++i * Y_STEP));
            pen.drawString("Close: " + close, startX, myMouseLoc.y + (++i * Y_STEP));
            pen.drawString("Volume: " + volum, startX, myMouseLoc.y + (++i * Y_STEP));
        }
    }

    /**
     * @param visual Visualizer to display
     */
    public void setVisualizer (Visualizer visual) {
        myVisual = visual;
    }

    /**
     *
     * @param data Date to set
     */
    public void setVisualizerData (DataModel data) {
        myVisual.setData(data);
    }
}
